package com.yycx.bpm.provider.common;

import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.yycx.bpm.provider.listener.FlowListInterceptor;
import com.yycx.bpm.provider.listener.FlowPageInterceptor;
import com.yycx.bpm.provider.service.FlowableTaskService;
import com.yycx.bpm.provider.service.PermissionService;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.model.PageParams;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.utils.SpringContextHolder;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.ValuedDataObject;
import org.flowable.common.engine.api.query.Query;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.engine.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

/**
 * 流程处理控制器父类
 *
 * @author zyf
 */
public abstract class BaseFlowableController {
    @Autowired
    protected ResponseFactory responseFactory;
    @Autowired
    protected RepositoryService repositoryService;
    @Autowired
    protected ManagementService managementService;
    @Autowired
    protected RuntimeService runtimeService;
    @Autowired
    protected FormService formService;
    @Autowired
    protected HistoryService historyService;
    @Autowired
    protected PermissionService permissionService;
    @Autowired
    protected FlowableTaskService flowableTaskService;
    @Autowired
    protected TaskService taskService;

    /**
     * 通用分页
     *
     * @param params
     * @param query
     * @param listInterceptor
     * @param allowedSortProperties
     * @param defaultDescSortProperty
     * @return
     */
    protected ResultBody pageList(Map params, Query query, Class<? extends FlowListInterceptor> listInterceptor, Map<String, QueryProperty> allowedSortProperties, QueryProperty defaultDescSortProperty) {
        CriteriaQuery cq = new CriteriaQuery(params);
        EntityMap paramsMap = new EntityMap(params);
        List list;
        Boolean isPager = cq.getPager();
        PageParams pageParams = cq.getPageParams();
        Boolean hanHandler = false;
        //扩展事件
        FlowPageInterceptor flowPageInterceptor = SpringContextHolder.getHandler(cq.getHandlerName(), FlowPageInterceptor.class);
        if (FlymeUtils.isNotEmpty(flowPageInterceptor)) {
            hanHandler = true;
            flowPageInterceptor.prepare(query, paramsMap);
        }
        if (!isPager) {
            list = query.list();
        } else {
            setQueryOrder(pageParams, query, allowedSortProperties, defaultDescSortProperty);
            list = query.listPage((int) pageParams.getOffset(), pageParams.getLimit());
        }
        //执行数据封装
        if (listInterceptor != null) {
            FlowListInterceptor interceptor = SpringContextHolder.getBean(listInterceptor);
            list = interceptor.execute(list);
        }
        //自定义业务数据扩展
        if (hanHandler) {
            pageParams.setRecords(flowPageInterceptor.complete(query, list, paramsMap));
        } else {
            pageParams.setRecords(list);
        }
        pageParams.setTotal(query.count());
        return ResultBody.ok(pageParams);
    }

    /**
     * 通用分页
     *
     * @param params
     * @param query
     * @param listInterceptor
     * @param allowedSortProperties
     * @return
     */
    protected ResultBody pageList(Map params, Query query, Class<? extends FlowListInterceptor> listInterceptor, Map<String, QueryProperty> allowedSortProperties) {
        return pageList(params, query, listInterceptor, allowedSortProperties, null);
    }


    /**
     * 设置排序
     *
     * @param pageParams
     * @param query
     * @param properties
     * @param defaultDescSortProperty
     */
    protected void setQueryOrder(PageParams pageParams, Query query, Map<String, QueryProperty> properties, QueryProperty defaultDescSortProperty) {
        String order = pageParams.getOrder();
        //如果有排序设置排序字段
        if (FlymeUtils.isNotEmpty(order)) {
            QueryProperty qp = properties.get(order);
            String sort = FlymeUtils.getString(pageParams.getSort(), SqlKeyword.DESC.name());
            query.orderBy(qp);
            if (sort.equals(SqlKeyword.ASC.name())) {
                query.asc();
            } else {
                query.desc();
            }
        }
    }

    /**
     * 只接收字符串
     *
     * @param message
     * @param arguments
     * @return
     */
    protected String messageFormat(String message, String... arguments) {
        return MessageFormat.format(message, (Object[]) arguments);
    }

    protected List getInterceptor(Class<? extends FlowListInterceptor> listInterceptor, List list) {
        FlowListInterceptor listWrapper = SpringContextHolder.getBean(listInterceptor);
        List result = listWrapper.execute(list);
        return result;
    }

    protected boolean isShowBusinessKey(String processDefinitionId) {
        List<ValuedDataObject> dataObjects = repositoryService.getBpmnModel(processDefinitionId).getMainProcess().getDataObjects();

        Process process = repositoryService.getBpmnModel(processDefinitionId).getMainProcess();

        Map<String, List<ExtensionElement>> extensionElements = process.getExtensionElements();
        if (extensionElements != null && !extensionElements.isEmpty() && extensionElements.get("properties") != null && extensionElements.get("properties").size() > 0) {
            List<ExtensionElement> properties = extensionElements.get("properties");
            for (ExtensionElement extensionElement : properties) {
                List<ExtensionElement> property = extensionElement.getChildElements().get("property");
                if (property != null && property.size() > 0) {
                    for (ExtensionElement propertyElement : property) {
                        String name = propertyElement.getAttributeValue(null, "name");
                        String value = propertyElement.getAttributeValue(null, "value");
                        if ("showBusinessKey".equals(name)) {
                            if (Boolean.valueOf(value)) {
                                return true;
                            } else {
                                return false;
                            }
                        }
                    }
                }
            }
        }
        if (dataObjects != null && dataObjects.size() > 0) {
            for (ValuedDataObject valuedDataObject : dataObjects) {
                if ("showBusinessKey".equals(valuedDataObject.getId())) {
                    if (valuedDataObject.getValue() instanceof String) {
                        return Boolean.valueOf((String) valuedDataObject.getValue());
                    } else if (valuedDataObject.getValue() instanceof Boolean) {
                        return (Boolean) valuedDataObject.getValue();
                    } else {
                        return false;
                    }
                }
            }
        }
        return false;
    }
}
